﻿using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;

namespace FileLog
{

    public sealed class FileLogger : ILogger
    {
        private readonly string _categoryName;
        private readonly FileLogOptins _optins;
        private readonly LogLevel _level;
        private readonly FileLoggingProcessor _processor;
        public FileLogger(
            string categoryName, 
            LogLevel level,
            FileLogOptins options, 
            FileLoggingProcessor processor)
        {
            _categoryName=categoryName;
            _optins=options;
            _level=level;
            _processor = processor;
        }
        public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
        {
            if (!IsEnabled(logLevel))
                return;
            var timestamp = DateTimeOffset.Now;
            var msg = formatter(state, exception);
            var log = _optins.LogFormatter!.Invoke(_categoryName, logLevel, exception, msg, timestamp);
            if (log != null)
            {
                _processor.EnqueueLog(log, timestamp);
            }
        }

        public bool IsEnabled(LogLevel logLevel) => logLevel >= _optins.MinimumLevel;

        public IDisposable? BeginScope<TState>(TState state) where TState : notnull => default!;
    }

    public class FileLogger<T> : ILogger<T>
    {
        private readonly ILogger _logger;

        /// <summary>
        /// Creates a new <see cref="Logger{T}"/>.
        /// </summary>
        /// <param name="factory">The factory.</param>
        public FileLogger(ILoggerFactory factory)
        {
            ThrowHelper.ThrowIfNull(factory,nameof(factory));

            _logger = factory.CreateLogger(GetCategoryName());
        }

        private string GetCategoryName() 
        {
            var nameSpace= typeof(T).Namespace;
            var spaceArr=nameSpace.Split('.');
            if (spaceArr.Length == 1) return nameSpace;
            var result = string.Join(".", spaceArr.Take(2));
            return result;
        }
        public IDisposable? BeginScope<TState>(TState state) where TState : notnull
        {
           return _logger.BeginScope(state);
        }

        public bool IsEnabled(LogLevel logLevel)
        {
            return _logger.IsEnabled(logLevel);
        }

        public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
        {
            _logger.Log(logLevel, eventId, state, exception, formatter);
        }
    }
}
